var EventEmitter = require('events').EventEmitter;
var Util         = require("util");

var stream = function() {
    EventEmitter.call(this);
    this._data = undefined;
    this._name = "json";
}

Util.inherits(stream, EventEmitter);

stream.prototype.__defineGetter__("name", function() { return this._name; });

module.exports = stream;

stream.prototype.compose = function(protoMessage) {
    var str = JSON.stringify({
        iResultCode     :   protoMessage.iResultCode,
        sResultDesc     :   protoMessage.sResultDesc,
        iRequestId      :   protoMessage.origin.iRequestId,
        sFuncName       :   protoMessage.origin.sFuncName,
        Arguments       :   protoMessage.appBuffer
    });

    var len = 4 + Buffer.byteLength(str);
    var buf = new Buffer(len);
    buf.writeUInt32BE(len, 0);
    buf.write(str, 4);

    return buf;
}

var ProtoMessageRequest = function() {
    this.origin         = undefined;
    this.sFuncName      = undefined;
    this.iResultCode    = 0;
    this.sResultDesc    = "";
}

stream.prototype.feed = function(data) {
    var BinBuffer = data;
    if(this._data != undefined) {
        var temp = new Buffer(this._data.length + data.length);
        this._data.copy(temp, 0);
        data.copy(temp, this._data.length);
        this._data = undefined;
        BinBuffer = temp;
    }

    for(var pos = 0; pos < BinBuffer.length; ) {
        if(BinBuffer.length - pos < 4)
            break;
        var Length = BinBuffer.readUInt32BE(pos);
        if(pos + Length > BinBuffer.length)
            break;
        
        var result = JSON.parse(BinBuffer.slice(pos + 4, pos + Length).toString());
        
        var protoMessage = new ProtoMessageRequest();
        protoMessage.iResultCode    = 0;
        protoMessage.sResultDesc    = "";
        protoMessage.sFuncName      = result.sFuncName;
        protoMessage.origin         = {
            sFuncName   :   result.sFuncName,
            iRequestId  :   result.iRequestId,
            Arguments   :   result.Arguments
        };

        this.emit("message", protoMessage);
        pos += Length;
    }

    if(pos != BinBuffer.length) {
        this._data = new Buffer(BinBuffer.length - pos);
        BinBuffer.copy(this._data, 0, pos);
    }
}

stream.prototype.reset = function() {
    delete this._data;
    this._data = undefined;
}